
#include <bancopg.h>

/**
 * \param arq_conf passagem do caminho do arquivo de configuração da conexao com o banco de dados.
 */
BANCOPG::BANCOPG(const char *arq_conf)
  	{
	int i;
	string con_file[5];
	string::size_type localizacao;
	
	this->conn = NULL;
	this->query_result = 0;
	conf_file.append(arq_conf);
	this->conf.open(conf_file.c_str());

	//Fazendo a leitura do arquivo de configuração
	if (this->conf)
    	{
	  	for (i=0; i < 5; i++)
			{
			getline(this->conf,con_file[i]);
			//cout << con_file[i] << endl;
			}
	  	}
	
	this->conf.close();
  
	localizacao = con_file[0].find("=",0);
	if (localizacao != string::npos)
		  {  
		  //cout << con_file[0].substr(localizacao+1) << endl;
		  this->host.append(con_file[0].substr(localizacao+1));
		  }
	localizacao = con_file[1].find("=",0);
	if (localizacao != string::npos)
		{
		//cout << con_file[1].substr(localizacao+1) << endl;
		this->banco.append(con_file[1].substr(localizacao+1));
		}
	localizacao = con_file[2].find("=",0);
	if (localizacao != string::npos)
		{
		//cout << con_file[2].substr(localizacao+1) << endl;
		this->user.append(con_file[2].substr(localizacao+1)); 
		}
	localizacao = con_file[3].find("=",0);
	if (localizacao != string::npos)
		{
		//cout << con_file[3].substr(localizacao+1) << endl;
		this->senha.append(con_file[3].substr(localizacao+1)); 
		}
	localizacao = con_file[4].find("=",0);
	if (localizacao != string::npos)
		{
		//cout << con_file[4].substr(localizacao+1) << endl;
		this->tipo = atoi(con_file[4].substr(localizacao+1).c_str());
		}
  	this->conectar();
  	}

BANCOPG::~BANCOPG()
	{
	if (this->conn != NULL)
		{
		PQfinish(this->conn);
		}
	}

void BANCOPG::conectar()
	{
	string coneccao;

	this->mensagem.clear();
	coneccao.append("hostaddr=");
	coneccao=coneccao+host;
	coneccao.append(" dbname=");
  	coneccao=coneccao+banco;
  	coneccao.append(" user=");
  	coneccao=coneccao+user;
  	coneccao.append(" password=");
  	coneccao=coneccao+senha;
	coneccao.append(" sslmode=");
	if (this->tipo == 1)
		{
		coneccao.append("require");
		}
	else
		{
		coneccao.append("disable");
		}

  	conn = PQconnectdb(coneccao.c_str());
  	if (PQstatus(this->conn) == CONNECTION_OK)
		{
		this->conectado = 1;
		this->mensagem.append("Conectado com sucesso!");
		}
  	else
		{
		this->conectado = 0;
		this->mensagem.append("Falha ao conectar!\n");
		this->mensagem.append(PQerrorMessage(this->conn));
		}
 	}

/**
 * \param query recebe uma consulta SQL que será executada na base de dados.
 */
void BANCOPG::executar(char *query)
	{
	int j;
	if (this->conectado)
		{
		this->result = NULL;
		this->result = PQexec(this->conn,query);
		switch(PQresultStatus(this->result))
			{
			case PGRES_COMMAND_OK:
			    {
				this->query_result = 1;
				break;
				}
			case PGRES_TUPLES_OK:
			    {
				this->query_result = 2;
				this->registros = PQntuples(this->result);
				this->colunas = PQnfields(this->result);
				nome_colunas.clear();
				for (j=0; j < colunas; j++)
					{
					nome_colunas.push_back ((char*)PQfname(result,j));
					}
				break;
				}
			case PGRES_BAD_RESPONSE:
			case PGRES_NONFATAL_ERROR:
			case PGRES_FATAL_ERROR:
			case PGRES_EMPTY_QUERY:
			case PGRES_COPY_OUT:
			case PGRES_COPY_IN:
				{
				this->query_result = 3;
				mensagem.clear();
				mensagem.append(PQresultErrorMessage(this->result));
				break;
				}
		 	}
		}
	}

/**
 * Percorre os resultado de um SQL no PostgreSQL em forma de Matriz [linha][coluna]
 * \param linha refere-se a linha que deseja-se recuperar na consulta.
 * \param coluna refere-se a coluna que deseja-se recuperar na consulta.
 * \return A informação da linha e coluna selecionadas no formato de 'const char'
 */
const char* BANCOPG::resultado(int linha, int coluna)
	{
	char *dados;
	int tam;

  	if (((linha >= 0)&&(linha < this->registros))&&((coluna >= 0)&&(coluna < this->colunas)))
		{
		if (PQgetvalue(this->result,linha,coluna) != NULL)
			{
			tam = strlen(PQgetvalue(this->result,linha,coluna));
			dados = new char[tam+1];
			strcpy(dados,PQgetvalue(this->result,linha,coluna));
			}
		else
			{
			dados = new char[2];
			strcpy(dados,"");
			}
		}
  	else
		{
		dados = new char[30];
		strcpy(dados,"Posi\303\247\303\243o n\303\243o encontrada!");
		}
  	return dados;
  	}

void BANCOPG::resultado()
	{
	int i, j;
	vector<string> valores;

	resultados.clear();
	for (i=0; i < registros; i++)
		{
		valores.clear();
		for (j=0; j < colunas; j++)
			{
			valores.push_back ((char *)resultado(i,j));
			}
		resultados.push_back (valores);
		}
	}